package com.UnionPayCenter.vastchain;

import com.UnionPayCenter.enums.ErrorCodeEnum;
import com.UnionPayCenter.exception.ApiException;
import com.UnionPayCenter.sms.StringUtil;
import com.UnionPayCenter.vastchain.response.VastChainBaseResponse;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.http.HttpStatus;
import org.springframework.http.HttpMethod;

import java.io.IOException;
import java.net.MalformedURLException;

/**
 * 宇链client
 */
@Slf4j
public class VastChainClient {


    public <R extends VastChainBaseResponse> R doGet(String url, String query, Class<R> resultType) {
        try {
            SigningResult signResult = Signature.sign(HttpMethod.GET.name(), url, query, null);
            url = signResult.fullUri;
        } catch (MalformedURLException e) {
            log.error("vast chain encrypt error: {}", e.getMessage(), e);
            throw new ApiException(ErrorCodeEnum.SC2.code(), "宇链加密失败");
        }
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        return doRequest(request, resultType);
    }

    public <R extends VastChainBaseResponse> R doPost(String url, String content, String mediaType, Class<R> resultType) {

        if (StringUtil.isNullOrEmpty(mediaType)) {
            mediaType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
        }

        try {
            SigningResult signResult = Signature.sign(HttpMethod.POST.name(), url, null, content);
            url = signResult.fullUri;
        } catch (MalformedURLException e) {
            log.error("vast chain encrypt error: {}", e.getMessage(), e);
            throw new ApiException(ErrorCodeEnum.SC2.code(), "宇链加密失败");
        }
        MediaType okMediaType = MediaType.parse(mediaType);
        RequestBody body = RequestBody.create(okMediaType, content);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .addHeader("Content-Type", mediaType)
                .build();
        return doRequest(request, resultType);
    }

    public <R extends VastChainBaseResponse> R doPut(String url, String content, String mediaType, Class<R> resultType) {

        if (StringUtil.isNullOrEmpty(mediaType)) {
            mediaType = org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
        }

        try {
            SigningResult signResult = Signature.sign(HttpMethod.PUT.name(), url, null, content);
            url = signResult.fullUri;
        } catch (MalformedURLException e) {
            log.error("vast chain encrypt error: {}", e.getMessage(), e);
            throw new ApiException(ErrorCodeEnum.SC2.code(), "宇链加密失败");
        }
        MediaType okMediaType = MediaType.parse(mediaType);
        RequestBody body = RequestBody.create(okMediaType, content);
        Request request = new Request.Builder()
                .url(url)
                .put(body)
                .addHeader("Content-Type", mediaType)
                .build();
        return doRequest(request, resultType);
    }

    private <R extends VastChainBaseResponse> R doRequest(Request request, Class<R> resultType) {
        try {
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
                    .build();
            Response response = client.newCall(request).execute();
            int status = response.code();
            if (HttpStatus.SC_OK != status && HttpStatus.SC_BAD_REQUEST != status) {
                log.error("vastchain error, code: {}, message: {}", status, response.body());
                throw new ApiException(status, "调用宇链失败");
            }
            String responseBody = response.body().string();
            R vastChainResponse = JSONObject.parseObject(responseBody, resultType);
            log.info("vastchain signup response: {}", responseBody);

            if (!"success".equals(vastChainResponse.getStatus())) {
                throw new ApiException(ErrorCodeEnum.SC2.code(), vastChainResponse.getMsg());
            }
            return vastChainResponse;
        } catch (IOException e) {
            log.error("invoke vast chain error: {}", e.getMessage(), e);
            throw new ApiException(ErrorCodeEnum.SC2.code(), "调用宇链io异常");
        }
    }

}
